package com.shenzhen.group.niuniu.play;

import com.shenzhen.group.common.entity.HandCardGroupBase;
import com.shenzhen.group.common.game.InvestGameTemplate;
import com.shenzhen.group.common.game.Position;
import com.shenzhen.group.common.player.Player;
import com.shenzhen.group.niuniu.card.NiuniuCardGroup;
import com.shenzhen.group.niuniu.card.NiuniuHandCardGroup;
import com.shenzhen.group.niuniu.card.NiuniuOperation;
import com.shenzhen.group.niuniu.controller.GameContext;
import com.shenzhen.group.niuniu.result.NiuniuCardResult;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 牛牛抽象游戏类
 * @author 周赛波
 * @version v1.0.0
 * @date 2021/12/26 1:15
 */
@Slf4j
@Data
public abstract class NiuniuAbstractGame extends InvestGameTemplate {
    /**
     * 最少玩家数量
     */
    private static final Integer MIN_PLAYER_NUM = 2;

    /**
     * 最多玩家数量
     */
    private static final Integer MAX_PLAYER_NUM = 10;

    private static final String IN_BET = ",Please bet!Press enter to end!";

    /** 是否洗牌 */
    protected String shuffle = "Y";

    @Override
    protected void settlement() {
        Position dealerPosition = positions.stream().filter(t -> t.getPlayer().getRoleEnum() == Player.RoleEnum.DEALER).findFirst().orElse(positions.get(0));
        Player dealerPlayer = dealerPosition.getPlayer();
        HandCardGroupBase handCard = dealerPosition.getHandCardGroupBase();
        NiuniuHandCardGroup niuniuHandCardGroup = null;
        if (handCard instanceof NiuniuHandCardGroup) {
            niuniuHandCardGroup = (NiuniuHandCardGroup) handCard;
        } else {
            throw new IllegalArgumentException("非法参数异常！");
        }
        NiuniuCardResult dealerCal = niuniuHandCardGroup.calculateHandCardGroup();

        Map<Long, BigDecimal> collect = positions.stream().map(Position::getPlayer).collect(Collectors.toMap(Player::getId, Player::getBalance));
        Map<Long, NiuniuCardResult> resCalMap = new HashMap<>();
        resCalMap.put(dealerPlayer.getId(), dealerCal);
        positions.stream().filter(t -> t.getPlayer().getRoleEnum() != Player.RoleEnum.DEALER).forEach(t -> {
            NiuniuCardResult temp = ((NiuniuHandCardGroup) t.getHandCardGroupBase()).calculateHandCardGroup();
            int compareInt = dealerCal.compareTo(temp);
            Player player = t.getPlayer();
            resCalMap.put(player.getId(), temp);
            String info = "";
            if (compareInt > 0) {
                // 庄家赢钱
                dealerPlayer.setBalance(dealerPlayer.getBalance().add(t.getBet().multiply(new BigDecimal(dealerCal.getMagnification()))));
                // 闲家输钱
                player.setBalance(player.getBalance().subtract(t.getBet().multiply(new BigDecimal(dealerCal.getMagnification()))));
            } else if (compareInt < 0) {
                // 闲家赢钱
                player.setBalance(player.getBalance().add(t.getBet().multiply(new BigDecimal(temp.getMagnification()))));
                // 庄家输钱
                dealerPlayer.setBalance(dealerPlayer.getBalance().subtract(t.getBet().multiply(new BigDecimal(temp.getMagnification()))));
            } else {
                // 暂时没有
            }
        });

        for (int i = 0; i < positions.size(); i++) {
            Player temp = positions.get(i).getPlayer();
            String info = "闲家";
            BigDecimal bet = positions.get(i).getBet();
            String betString = bet == null ? "" : bet.toString();
            if (Player.RoleEnum.DEALER == temp.getRoleEnum()) {
                info = "庄家";
            }
            log.info("{}\t{}\t{}\t本局结算：(下注金额：{}\t收益金额：{}\t余额：{})", info, temp.getName(), getDes(resCalMap.get(temp.getId())), betString, temp.getBalance().subtract(collect.get(temp.getId())), temp.getBalance());
        }
        BigDecimal reduce = positions.stream().map(Position::getPlayer).map(Player::getBalance).reduce(new BigDecimal(0), BigDecimal::add);
        // 结算结束，清空桌子的押注
        positions.forEach(t -> {
            t.setBet(null);
        });
        log.info("所有总余额：" + reduce);

    }

    private String getDes(NiuniuCardResult dealerCal) {
        String des = "";
        if (dealerCal.getNiu() > 0 && dealerCal.getNiu() < 10) {
            des = "牛" + dealerCal.getNiu();
        } else if (dealerCal.getNiu() == 10) {
            des = "牛牛";
        } else {
            des = "没牛";
        }
        return des;
    }

    @Override
    protected void initShuffle() {
        if ("Y".equals(shuffle)) {
            Collections.shuffle(this.cardGroupBase.getCards());
        }
        this.positions.forEach(e -> e.getPlayer().setRoleEnum(Player.RoleEnum.PLAYER));
        List<Player> players = this.positions.stream().map(Position::getPlayer).collect(Collectors.toList());
        Collections.shuffle(players);
        for (Position position : this.positions) {
            if (position.getPlayer().getId().compareTo(players.get(0).getId()) == 0) {
                position.getPlayer().setRoleEnum(Player.RoleEnum.DEALER);
                GameContext.getDealContext().set(position.getPlayer());
            }
        }
    }

    @Override
    protected void initLicensing() {
        NiuniuOperation niuniuOperation = new NiuniuOperation();
        niuniuOperation.dealCards(this.cardGroupBase, this.positions);
    }

    @Override
    protected void initDet() {
        //        List<String> nameList = this.positions.stream()
//                .filter(e -> (e.getPlayer() != null && e.getPlayer().getRoleEnum() != Player.RoleEnum.DEALER))
//                .peek(e -> e.setBet(new BigDecimal(0)))
//                .map(e -> e.getPlayer().getName())
//                .collect(Collectors.toList());
//        List<BigDecimal> betList = this.positions.stream()
//                .filter(e -> (e.getPlayer() != null && e.getPlayer().getRoleEnum() != Player.RoleEnum.DEALER))
//                .map(e -> e.getPlayer().getBalance())
//                .collect(Collectors.toList());
//        Scanner sc = new Scanner(System.in);
//        System.out.println(String.join("、", nameList) + IN_BET);
//        int i = 1;
//        while (i < this.positions.size() && sc.hasNext()) {
//            Position position = this.positions.get(i);
//            if (sc.hasNextFloat()) {
//                BigDecimal bet = BigDecimal.valueOf(sc.nextFloat());
//                if (bet.compareTo(position.getPlayer().getBalance()) == 1) {
//                    // 超过视为all in
//                    position.setBet(position.getPlayer().getBalance());
//                } else {
//                    position.setBet(bet);
//                }
//            }
//            i++;
//        }


        // positions.stream().filter(t -> t.getPlayer().getRoleEnum() != Player.RoleEnum.DEALER).forEach(t -> {
        //     if (t.getPlayer().getId() == 1) {
        //         t.setBet(this.strategyMap.get(t.getPlayer().getId()).fluctuateStrategy(t.getPlayer()));
        //     } else if (t.getPlayer().getId() == 2) {
        //         t.setBet(this.strategyMap.get(t.getPlayer().getId()).avgStrategy(t.getPlayer()));
        //     } else if (t.getPlayer().getId() == 3) {
        //         t.setBet(this.strategyMap.get(t.getPlayer().getId()).paragraphStrategy(t.getPlayer()));
        //     } else if (t.getPlayer().getId() == 4) {
        //         t.setBet(this.strategyMap.get(t.getPlayer().getId()).RandomStrategy(t.getPlayer(), 10));
        //     } else {
        //         t.setBet(this.strategyMap.get(t.getPlayer().getId()).fluctuateStrategy(t.getPlayer()));
        //     }
        // });

        positions.stream().filter(t -> t.getPlayer().getRoleEnum() != Player.RoleEnum.DEALER).forEach(t -> {
            t.setBet(this.strategyMap.get(t.getPlayer().getId()).smallRandomStrategy(300, 5));
        });
        Map<Long, String> betMap = positions.stream().filter(position -> position.getBet() != null).collect(Collectors.toMap(position -> position.getPlayer().getId(), position -> position.getBet().toString()));
        GameContext.getDetContext().set(betMap);
        GameContext.getPositionContext().set(positions);
    }

    @Override
    protected void initCardGroupBase() {
        this.cardGroupBase = new NiuniuCardGroup();
        cardGroupBase.initCards();
    }
}
